package com.github.xzb617.client.route.scg.rules.impl;

import com.github.xzb617.client.route.scg.constant.RouteRule;
import com.github.xzb617.client.route.scg.props.RouteProperties;
import com.github.xzb617.client.route.scg.rules.RoutingRule;
import com.github.xzb617.client.route.scg.rules.ratio.WeightCalculator;
import com.github.xzb617.client.route.scg.utils.RouteUtil;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpRequest;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class HeaderRoutingRule implements RoutingRule {

    @Override
    public void matches(ServerHttpRequest request, HttpHeaders httpHeaders, String ipAddr, RouteProperties.RuleProperties config, RoutingRule routingRuleChain) {
        Map<String, Map<String, RouteRule>> rules = config.getRules();
        Map<String, RouteRule> headerRuleMap = rules.get("HEADER");
        if (headerRuleMap!=null && !headerRuleMap.isEmpty()) {
            RouteRule matchedRouteRule = this.matchHeader(request, headerRuleMap);
            if (matchedRouteRule != null) {
                boolean available = WeightCalculator.available(ipAddr, matchedRouteRule.getWeight());
                if (available) {
                    // 匹配成功，打上标签
                    RouteUtil.assignRouteLabel(httpHeaders, matchedRouteRule, true);
                } else {
                    RouteUtil.assignRouteLabel(httpHeaders, matchedRouteRule, false);
                }
            }
        }
    }

    private RouteRule matchHeader(ServerHttpRequest request, Map<String, RouteRule> headerRuleMap) {
        RouteRule matchedRouteRule = null;
        HttpHeaders headers = request.getHeaders();
        Set<Map.Entry<String, List<String>>> entries = headers.entrySet();
        for (Map.Entry<String, List<String>> entry : entries) {
            String headerName = entry.getKey();
            if (headerRuleMap.containsKey(headerName)) {
                RouteRule routeRule = headerRuleMap.get(headerName);
                String headerValue = request.getHeaders().getFirst(headerName);
                String callerValue = routeRule.getCallerValue();
                if (callerValue!=null && callerValue.equals(headerValue)) {
                    matchedRouteRule = routeRule;
                    break;
                }
            }
        }
        return matchedRouteRule;
    }

}
